package com.awesome.network.call;


import com.awesome.network.OkHttpHelper;
import com.awesome.network.callback.Callback;
import com.awesome.network.callback.FailureRunnable;
import com.awesome.network.callback.SuccessRunnable;
import com.awesome.network.exception.NetworkUnavailableException;
import com.awesome.network.util.NetworkStateHelper;

import java.io.IOException;
import java.lang.reflect.Type;

import okhttp3.Call;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Author: JFangZ
 * Email:janezhang1901@163.com
 * Date: 2021/4/28 17:13
 * Description:Call impl for request result need transform.
 */
public class TransformCallImpl<I, O> extends AbsCall<O> {
    private final Type mType;
    private final ResponseTransformer<I, O> mResponseTransformer;

    public TransformCallImpl(Call call, Type type, ResponseTransformer<I, O> responseTransformer) {
        super(call);
        mType = type;
        mResponseTransformer = responseTransformer;
    }

    @Override
    public void enqueue(Callback<O> callback) {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                callback.onFailure(new NetworkUnavailableException());
                return;
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        mCall.enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mHandler.post(new FailureRunnable<>(callback, e));
                OkHttpHelper.SINGLETON.removeCall(TransformCallImpl.this);
            }

            @Override
            public void onResponse(Call call, Response response) {
                OkHttpHelper.SINGLETON.removeCall(TransformCallImpl.this);
                try {
                    String string = response.body().string();
                    I i = mGson.fromJson(string, mType);
                    O o = mResponseTransformer.transform(i);
                    mHandler.post(new SuccessRunnable<>(callback, o));
                } catch (Exception e) {
                    mHandler.post(new FailureRunnable<>(callback, e));
                }
            }
        });
    }

    @Override
    public O execute() throws Exception {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                throw new NetworkUnavailableException();
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        Response response = mCall.execute();
        OkHttpHelper.SINGLETON.removeCall(this);
        ResponseBody responseBody = response.body();
        I i = mGson.fromJson(responseBody.string(), mType);
        return mResponseTransformer.transform(i);
    }

    @Override
    public <O1> TransformCallImpl<O, O1> transform(ResponseTransformer<O, O1> responseTransformer) {
        return new TransformCallImpl(mCall, mType, responseTransformer);
    }
}